/*
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is ST_EXT-S_UIMAST.
 *
 * The Initial Developer of the Original Code is
 * University of Rome, Tor Vergata
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 */

package it.uniroma2.art.uimast;


import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import it.uniroma2.art.semanticturkey.plugin.extpts.InterfaceServiceServlet;
import it.uniroma2.art.uimast.impl.modes.xpointer.XPointerModeService;
import it.uniroma2.art.uimast.servlet.UimaIntegration;
import it.uniroma2.art.uimast.xpts.ExportModeDriver;
import it.uniroma2.art.uimast.xpts.ExportModeService;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
 * Activates the ST_EXT_S_UIMAST bundle, which extends the Semantic
 * Turkey middle layer, providing UIMA oriented services. Currently, there is
 * just a monolithic service, which forwards the requests to the adequate
 * servants.
 * 
 * @author <a href="mailto:manuel.fiorelli@gmail.com">Manuel Fiorelli</a>
 */
public class Activator implements BundleActivator, ServiceListener {

	/**
	 * Constructs an <code>Activator</code> object. A bundle activator must
	 * expose a public default constructor.
	 */
	public Activator() {
		// Nothing TO-DO
	}

	// the methods start and stop inherit their documentation comments from the
	// BundleActivator interface.

	public void start(BundleContext bundleContext) throws Exception {
		// Saves the bundle context
		context = bundleContext;
		
		// Registers itself as a service listener
		bundleContext.addServiceListener(this);
		
		// synchronization prevents that the listener is called, while performing this operation
		synchronized (this) {
			// Generates artificial events for services already registered
			ServiceReference [] refs = context.getServiceReferences(null, null);
			
			for (ServiceReference sr : refs)
				serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, sr));
		}
		
		// Saves this activation
		activator = this;
		
		// Publishes the XPointerExportMode
		Properties props = new Properties();
		props.put("Mode", "xpointer");
		bundleContext.registerService(ExportModeService.class.getName(),
				new XPointerModeService(), props);
		
		// Publishes the service, which will extend the middle layer of Semantic Turkey
		bundleContext.registerService(InterfaceServiceServlet.class.getName(),
				new UimaIntegration(UIMA_INTEGRATION_SERVICE), null);
	}

	public void stop(BundleContext bundlecontext) throws Exception {
		activator = null;
	}
	
	/**
	 * Gets an export mode provider.
	 * @param mode the export mode
	 * @return a mode provider, or {@code null} if {@code mode} isn't supported
	 */
	public synchronized ExportModeDriver getExportModeProvider(String mode) {
		ServiceReference sr = modeServices.get(mode);
		
		if (sr == null)
			return null;
		
		ExportModeService service = (ExportModeService)context.getService(sr);
		
		try {
			return service.getProvider();
		} finally {
			context.ungetService(sr);
		}
		
	}
	
	public synchronized void serviceChanged(ServiceEvent event) {
		
		ServiceReference sr = event.getServiceReference();
		
		String[] cls = (String[])sr.getProperty("objectClass");
		boolean good = false;
		
		for(String c : cls) {
			if (c.equals(ExportModeService.class.getName())) {
				good = true;
				break;
			}
		}
		
		if (!good) {
			return; 
		}
		
		String mode = (String)sr.getProperty("Mode");
				
		switch (event.getType()) {
			case ServiceEvent.REGISTERED:
				modeServices.put(mode, sr);				
				break;
			case ServiceEvent.UNREGISTERING:
				if (modeServices.get(mode) == sr) {
					modeServices.remove(mode);
				}
				break;
		}
	}

	/**
	 * Current activator instance
	 */
	public static Activator activator = null;

	/**
	 * The bundle context
	 */
	private BundleContext context;
	
	/**
	 * A collection of tracked services.
	 */
	private Map<String, ServiceReference> modeServices = new HashMap<String, ServiceReference>();
	
	/**
	 * The service identifier.
	 */
	private static final String UIMA_INTEGRATION_SERVICE = "UimaIntegration";
}
